package main

import (
	"math"
	"fmt"
)

/*
√ 无论是panic还是返回错误，都使用自定义异常InvalidRadiusError的实例来操作
*/

/*自定义异常InvalidRadiusError*/
type InvalidRadiusError struct {
	//非法半径
	Radius float64

	//可接受的最小半径
	MinRadius float64

	//可接受的最大半径
	MaxRaius float64
}

func (ire *InvalidRadiusError) Error() string {
	info := fmt.Sprintf("%.2f是非法半径，合法半径的范围是[%.2f,%.2f]\n", ire.Radius, ire.MinRadius, ire.MaxRaius)
	return info
}

/*工厂方法*/
func NewInvalidRadiusError(radius float64) *InvalidRadiusError {
	ire := new(InvalidRadiusError)
	ire.MinRadius = 5
	ire.MaxRaius = 50
	ire.Radius = radius
	return ire
}

/*求玩具球的体积*/
func GetToyBallVolumn3(radius float64) (volumn float64, err error) {
	if radius < 0 {
		//panic(&InvalidRadiusError{radius,5,50})
		panic(NewInvalidRadiusError(radius))
	}

	//半径如果不在取值范围[5,50]内，温和地返回错误
	if radius < 5 || radius > 50 {
		//err = &InvalidRadiusError{radius,5,50}
		err = NewInvalidRadiusError(radius)
		return
	}

	return (4 / 3.0) * math.Pi * math.Pow(radius, 3), nil
}

func main() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()
	//volumn, err := GetToyBallVolumn2(10)
	volumn, err := GetToyBallVolumn3(-0.5)
	if err != nil {
		fmt.Println("获取体积失败，err=", err)
	} else {
		fmt.Println("小球的体积是", volumn)
	}

}
